using System;
using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// This class has all the settings you can edit for fog.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "DepthBufferAttributes", Namespace = "SharpGL.SceneGraph")]
    public class DepthBufferAttributes : OpenGLAttributes
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.DepthBuffer;

        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private bool? enableDepthTest;
        [DataMember()]
        private DepthFunction? depthFunction;
        [DataMember()]
        private float? depthClearValue;
        [DataMember()]
        private bool? enableDepthWritemask;

        #endregion Private Fields

        #region Protected Methods

        protected override void OnDeserializing()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="DepthBufferAttributes"/> class.
        /// </summary>
        public DepthBufferAttributes()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>
        /// True if any attributes are set
        /// </returns>
        public override bool AreAnyAttributesSet()
        {
            return enableDepthTest.HasValue ||
                depthFunction.HasValue ||
                depthClearValue.HasValue ||
                enableDepthWritemask.HasValue;
        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            EnableDepthTest = null;
            DepthFunction = null;
            DepthClearValue = null;
            EnableDepthWritemask = null;
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            if (enableDepthTest.HasValue) gl.EnableIf(OpenGL.GL_DEPTH_TEST, enableDepthTest.Value);
            if (depthFunction.HasValue) gl.DepthFunc(depthFunction.Value);
            if (depthClearValue.HasValue) gl.ClearDepth(depthClearValue.Value);
            if (enableDepthWritemask.HasValue) gl.EnableIf(OpenGL.GL_DEPTH_WRITEMASK, enableDepthWritemask.Value);
        }

        #endregion Public Methods

        #region Public Properties

        /// <summary>
        /// Gets or sets the enable depth writemask.
        /// </summary>
        /// <value>
        /// The enable depth writemask.
        /// </value>
        [Description("EnableDepthWritemask"), Category("Depth Buffer attributes")]
        public bool? EnableDepthWritemask
        {
            get { return enableDepthWritemask; }
            set
            {
                if (enableDepthWritemask != value)
                {
                    enableDepthWritemask = value;

                    NotifyPropertyChanged("EnableDepthWritemask");
                }
            }
        }

        /// <summary>
        /// Gets or sets the depth clear value.
        /// </summary>
        /// <value>
        /// The depth clear value.
        /// </value>
        [Description("DepthClearValue"), Category("Depth Buffer attributes")]
        public float? DepthClearValue
        {
            get { return depthClearValue; }
            set
            {
                if (depthClearValue != value)
                {
                    depthClearValue = value;

                    NotifyPropertyChanged("DepthClearValue");
                }
            }
        }

        /// <summary>
        /// Gets or sets the depth function.
        /// </summary>
        /// <value>
        /// The depth function.
        /// </value>
        [Description("DepthFunction"), Category("Depth Buffer attributes")]
        public DepthFunction? DepthFunction
        {
            get { return depthFunction; }
            set
            {
                if (depthFunction != value)
                {
                    depthFunction = value;

                    NotifyPropertyChanged("DepthFunction");
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable depth test.
        /// </summary>
        /// <value>
        /// The enable depth test.
        /// </value>
        [Description("EnableDepthTest"), Category("Depth Buffer attributes")]
        public bool? EnableDepthTest
        {
            get { return enableDepthTest; }
            set
            {
                if (enableDepthTest != value)
                {
                    enableDepthTest = value;

                    NotifyPropertyChanged("EnableDepthTest");
                }
            }
        }

        #endregion Public Properties
    }
}
